import { defineVirtualModule, generageImports } from './_utils'
import utilsModule from './utils'
import wasmModule from './wasm'
import { once } from 'lodash-es'
import chalk from 'chalk'
import { resolveModuleId, safeRequire } from '../../utils'
import * as pkg from '../../../package.json'

export default defineVirtualModule(
  'wasm-virutal:wasm-asc-helper',
  once(() => {
    const asBindLoaderId = resolveModuleId('as-bind/dist/as-bind.esm.js')
    const asLoaderId = resolveModuleId('@assemblyscript/loader')

    if (asBindLoaderId) {
      console.info(
        chalk.yellow`[${pkg.name}]: Found "as-bind" loader dependency. Version is ${
          safeRequire('as-bind/package.json')?.version
        }.`
      )
    } else if (asLoaderId) {
      console.info(
        chalk.yellow`[${pkg.name}]: Found "@assemblyscript/loader" loader dependency. Version is ${
          safeRequire('@assemblyscript/loader/package.json')?.version
        }.`
      )
    }

    let loaderId
    if ((loaderId = asBindLoaderId ?? asLoaderId)) {
      return `
      /*#__PURE__*/ import { instantiate as _instantiate, instantiateSync as _instantiateSync } from ${JSON.stringify(
        loaderId
      )};
      ${generageImports(
        [utilsModule, ['readFile', 'readFileSync']],
        [wasmModule, ['WebAssembly_instantiateBuffer', 'WebAssembly_instantiateBufferSync']]
      )}
      const createInstantiateFromPath = (wasmPath, factory) => {
        let wasmSource;
        if (typeof factory !== "function") factory = (createInstance, importObject) => createInstance(importObject);
        const instantiate = async importObject => {
          let instance;
          if (!wasmSource) wasmSource = await readFile(wasmPath);
          const createInstance = async importObject => (instance = await _instantiate(wasmSource, importObject));
          await factory(createInstance, importObject, true);
          return instance;
        };
        const instantiateSync = importObject => {
          let instance;
          if (!wasmSource) wasmSource = readFileSync(wasmPath);
          const createInstance = importObject => (instance = _instantiateSync(wasmSource, importObject));
          factory(createInstance, importObject, false);
          return instance;
        };
        return {
          instantiate,
          instantiateSync,
        };
      };
      const createInstantiateFromBuffer = (wasmSource, factory) => {
        if (typeof factory !== "function") factory = (createInstance, importObject) => createInstance(importObject);
        const instantiate = async importObject => {
          let instance;
          const createInstance = async importObject => (instance = await _instantiate(wasmSource, importObject));
          await factory(createInstance, importObject, true);
          return instance;
        };
        const instantiateSync = importObject => {
          let instance;
          const createInstance = importObject => (instance = _instantiateSync(wasmSource, importObject));
          factory(createInstance, importObject, false);
          return instance;
        };
        return {
          instantiate,
          instantiateSync,
        };
      };
      `
    } else {
      return generageImports([wasmModule, wasmModule.exports])
    }
  }),
  wasmModule.exports
)
